﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using IRC.NET.Users;

namespace IRC.NET.Commands
{
    public delegate void ChannelEventHandler(object sender, ChannelEventArgs args);

    public class JoinCommand : TwoWayCommandBase
    {
        private static readonly string CHANNEL_FORWARD_PATTERN = @"^(?<old>{0})\s(?<new>#[^\s]+)\s+:(?<message>.*)$";
        private static readonly string JOIN_COMPLETE_PATTERN = @"^JOIN :(?<channel>{0})$";

        private static readonly string COMMAND_PREFIX = "JOIN";

        #region Events
        public event ChannelEventHandler JoinComplete;
        #endregion

        public string ChannelName
        {
            get { return ((string)this.Parameters["Channel"]); }
            set { this.Parameters["Channel"] = value; }
        }

        private Channel _channel;

        private IrcServer _server;

        public JoinCommand(IrcServer server, string channel)
            : base(COMMAND_PREFIX)
        {
            SetParameter("Channel", channel);
            this._server = server;
            this._channel = new Channel();
        }

        public override bool IsResponse(ServerReply message)
        {
            // We need to see what the response here is.
            if ((message.MessageCode == ServerReply.RPL_FORWARD) || (message.MessageCode == ServerReply.ERR_LINKCHANNEL))
            {
                return(message.Message.StartsWith(ChannelName));
            }
            else if (message.MessageCode == ServerReply.RPL_TOPIC)
            {
                return (message.Message.StartsWith(ChannelName));
            }
            else if (message.MessageCode == ServerReply.RPL_NICKTIME)
            {
                return (message.Message.StartsWith(ChannelName));
            }
            else if (message.MessageCode == ServerReply.RPL_NAMREPLY)
            {
                return(message.Message.StartsWith("@ " + ChannelName));
            }
            else if (message.MessageCode == ServerReply.RPL_ENDOFNAMES)
            {
                return (message.Message.StartsWith(ChannelName));
            }
            
            return (false);
        }

        public override bool ProcessResponse(ServerReply message)
        {
            if ((message.MessageCode == ServerReply.RPL_FORWARD) || (message.MessageCode == ServerReply.ERR_LINKCHANNEL))
            {
                string pattern = ParseUtils.GetPattern(message.MessageCode);
                string[] parameters = ParseUtils.GetParameters(message.Message, pattern);
                ChannelName = parameters[1];
                this._channel.Name = ChannelName;
            }
            else if (message.MessageCode == ServerReply.RPL_TOPIC)
            {
                if (!message.Message.StartsWith(ChannelName))
                {
                    return (false);
                }

                int idx = message.Message.IndexOf(':');
                this._channel.Topic = message.Message.Substring(idx);
            }
            else if (message.MessageCode == ServerReply.RPL_NICKTIME)
            {
                // Don't do anything with this.
                return (false);
            }
            else if (message.MessageCode == ServerReply.RPL_NAMREPLY)
            {
                string msg = message.Message;
                if (msg.StartsWith("@ " + ChannelName))
                {
                    // Strip this.
                    msg = msg.Substring(msg.IndexOf(':'));
                }

                // Not split at the spaces.
                char[] delimeters = { ' ' };
                string[] names = msg.Split(delimeters);
                foreach (string name in names)
                {
                    if (name.StartsWith("+"))
                    {
                        // Operator
                        this._channel.Operators.Add(new ServerSideUser(name));
                    }
                    else if (!name.Equals(message.Username))
                    {
                        this._channel.Users.Add(new ServerSideUser(name));
                    }
                }
            }
            else if (message.MessageCode == ServerReply.RPL_ENDOFNAMES)
            {
                this.OnChannelJoined(new ChannelEventArgs(this._server, this._channel, ChannelEventType.Joined));
                return (true);
            }

            return (false);
        }

        protected void OnChannelJoined(ChannelEventArgs args)
        {
            if (this.JoinComplete != null)
            {
                this.JoinComplete(this, args);
            }
        }
    }
}
